function Objective = mvnrobj(Data, Design, Param, Covar, CovarFormat)
%MVNROBJ Log-likelihood for multivariate normal regression without missing data.
% Log-likelihood function based on current maximum likelihood parameter estimates without missing
% data.
%
%		Objective = mvnrobj(Data, Design, Param, Covar, CovarFormat);
%
% Inputs:
%	Data - NUMSAMPLES x NUMSERIES matrix with NUMSAMPLES samples of a NUMSERIES-dimensional random
%		vector. If a data sample has missing values (with NaNs), the sample is ignored (use
%		ECMMVNRMLE to handle missing data).
%	Design - Either a matrix or a cell-array that depends upon the value of NUMSERIES. If
%		NUMSERIES = 1, then Design is a NUMSAMPLES x NUMPARAMS matrix with known values. If
%		NUMSERIES > 1, then Design is a cell array with NUMSAMPLES cells, where each cell contains
%		a NUMSERIES x NUMPARAMS matrix of known values. Although, in general, the Design array
%		should not have NaN values, ignored samples due to NaN values in Data are also ignored in
%		the corresponding Design array.
%	Param - NUMPARAMS x 1 column vector of estimates for the parameters of the regression model.
%	Covar - NUMSERIES x NUMSERIES matrix of estimates for the covariance of the residuals of the
%		regression.
%
% Optional Inputs:
%	CovarFormat - String that specifies the format for the covariance matrix. The choices are:
%		'full' - Default method. Compute the full covariance matrix.
%		'diagonal' - Treat the covariance matrix as a diagonal matrix.
%
% Outputs:
%	Objective - A scalar that contains the log-likelihood of the multivariate normal regression
%		model.
%
% Notes:
%	This function requires Covar to be positive-definite.
%
% See also MVNRMLE, ECMMVNRMLE, ECMMVNROBJ.

%	Copyright 2005-2007 The MathWorks, Inc.
%	$Revision: 1.1.6.2 $ $Date: 2007/05/10 13:45:04 $

if nargin < 5 || isempty(CovarFormat)
	CovarFormat = 'full';
else
	if ~any(strcmpi(CovarFormat,{'full','diagonal'}))
		error('Finance:mvnrobj:InvalidCovarianceFormat', ...
			'Invalid format specified for covariance matrix.');
	end
end
if nargin < 4
	error('Finance:mvnrobj:MissingInputArg', ...
		'Missing required arguments Data, Design, Param, or Covar.');
end

if isempty(Data)
	error('Finance:mvnrobj:EmptyDataArray', ...
		'Empty required input argument Data.');
end
if isempty(Design)
	error('Finance:mvnrobj:EmptyDesignArray', ...
		'Empty required input argument Design.');
end
if isempty(Param)
	error('Finance:mvnrobj:EmptyParam', ...
		'Empty required input argument Param.');
end
if isempty(Covar)
	error('Finance:mvnrobj:EmptyCovar', ...
		'Empty required input argument Covar.');
end

Param = Param(:);

%[NumSamples, NumSeries, NumParams] = checkmvnrsetup(Data, Design, Param, Covar, true);

[NumSamples, NumSeries] = size(Data);

if strcmpi(CovarFormat,'full')
	[CholCovar, CholState] = chol(Covar);
	if CholState > 0
		error('Finance:mvnrobj:NonPosDefCov', ...
			'Covariance is not positive-definite.');
	end

	LogTwoPi = log(2.0 * pi);
	LogDetCovar = 2.0 * sum(log(diag(CholCovar)));

	Count = 0;
	Objective = 0.0;

	if iscell(Design)
		if numel(Design) > 1
			for k = 1:NumSamples
				if ~any(isnan(Data(k,:)))
					Count = Count + 1;
					Resid = CholCovar' \ (Data(k,:)' - Design{k} * Param);
					Objective = Objective - 0.5 * Resid' * Resid;
				end
			end
		else
			for k = 1:NumSamples
				if ~any(isnan(Data(k,:)))
					Count = Count + 1;
					Resid = CholCovar' \ (Data(k,:)' - Design{1} * Param);
					Objective = Objective - 0.5 * Resid' * Resid;
				end
			end
		end
	else
		for k = 1:NumSamples
			if ~isnan(Data(k))
				Count = Count + 1;
				Resid = CholCovar' \ (Data(k) - Design(k,:) * Param);
				Objective = Objective - 0.5 * Resid' * Resid;
			end
		end
	end
else
	InvCovar = diag(1 ./ diag(Covar));
	if sum(any(~isfinite(InvCovar)))
		error('Finance:mvnrobj:NonPosDefCov', ...
			'Covariance is not positive-definite.');
	end
	
	LogTwoPi = log(2.0 * pi);
	LogDetCovar = sum(log(diag(Covar)));
	
	Count = 0;
	Objective = 0.0;

	if iscell(Design)
		if numel(Design) > 1
			for k = 1:NumSamples
				if ~any(isnan(Data(k,:)))
					Count = Count + 1;
					Resid = Data(k,:)' - Design{k} * Param;
					Objective = Objective - 0.5 * Resid' * InvCovar * Resid;
				end
			end
		else
			for k = 1:NumSamples
				if ~any(isnan(Data(k,:)))
					Count = Count + 1;
					Resid = Data(k,:)' - Design{1} * Param;
					Objective = Objective - 0.5 * Resid' * InvCovar * Resid;
				end
			end
		end
	else
		for k = 1:NumSamples
			if ~isnan(Data(k))
				Count = Count + 1;
				Resid = Data(k) - Design(k,:) * Param;
				Objective = Objective - 0.5 * Resid' * InvCovar * Resid;
			end
		end
	end	
end

Objective = Objective - 0.5 * Count * (NumSeries * LogTwoPi + LogDetCovar);

if Count < 1
	error('Finance:mvnrobj:AllNaNData', ...
		'All records have missing data. Cannot compute log-likelihood.');
end
